import { computed, reactive, ref } from "vue"
import { pinia } from "@/store"
import { defineStore } from "pinia"
import { useTagsViewStore } from "./tags-view"
import { useSettingsStore } from "./settings"
import { getToken, removeToken, setToken } from "@/utils/cache/cookies"
import { resetRouter } from "@/router"
import { loginApi } from "@/api/login"
import { type LoginRequestData } from "@/api/login/types/login"
import { getUserInfoApi, getWorkExpectationsApi } from "@/api/user"
import { useResetReactive } from "@/hooks/useReset"

type basicInfoType = Omit<UserInfo, "userRole">

export const useUserStore = defineStore("user", () => {
  const token = ref<string>(getToken() || "")
  const roles = ref<string[]>([])
  const [basicInfo, resetBasicInfo] = useResetReactive<basicInfoType>({
    id: "",
    email: "",
    gender: 0,
    phone: "",
    userAvatar: "",
    userName: "",
    userProfile: ""
  })
  const workExpectations = reactive({
    studyingExperience: undefined as unknown as number,
    workPrice: undefined as unknown as number,
    workTime: undefined as unknown as number,
    workName: ""
  })
  const gender = computed(() => {
    return basicInfo.gender === 0 ? "女" : basicInfo.gender === 1 ? "男" : "未知"
  })

  const tagsViewStore = useTagsViewStore()
  const settingsStore = useSettingsStore()

  /** 登录 */
  const login = async ({ userAccount, userPassword }: LoginRequestData) => {
    const { data } = await loginApi({ userAccount, userPassword })
    setToken(data)
    token.value = data
  }
  /** 获取用户详情 */
  const getInfo = async () => {
    const { data } = await getUserInfoApi()
    for (const attr of Object.keys(basicInfo) as (keyof typeof basicInfo)[]) {
      if (Object.prototype.hasOwnProperty.call(data, attr)) {
        // @ts-expect-error
        basicInfo[attr] = data[attr]
      }
    }
    // 验证返回的 roles 是否为一个非空数组，否则塞入一个没有任何作用的默认角色，防止路由守卫逻辑进入无限循环
    roles.value = [data.userRole!]
  }
  /** 获取用户求职期望 */
  const getWorkExpectations = async () => {
    const { data } = await getWorkExpectationsApi()
    for (const attr of Object.keys(workExpectations)) {
      if (Object.prototype.hasOwnProperty.call(data, attr)) {
        // @ts-expect-error
        workExpectations[attr] = data[attr]
      }
    }
  }
  /** 模拟角色变化 */
  const changeRoles = async (role: string) => {
    const newToken = "token-" + role
    token.value = newToken
    setToken(newToken)
    // 用刷新页面代替重新登录
    window.location.reload()
  }
  /** 登出 */
  const logout = () => {
    removeToken()
    token.value = ""
    roles.value = []
    resetRouter()
    _resetTagsView()
    resetBasicInfo()
  }
  /** 重置 Token */
  const resetToken = () => {
    removeToken()
    token.value = ""
    roles.value = []
  }
  /** 重置 Visited Views 和 Cached Views */
  const _resetTagsView = () => {
    if (!settingsStore.cacheTagsView) {
      tagsViewStore.delAllVisitedViews()
      tagsViewStore.delAllCachedViews()
    }
  }

  return {
    token,
    roles,
    basicInfo,
    workExpectations,
    gender,
    login,
    getInfo,
    getWorkExpectations,
    changeRoles,
    logout,
    resetToken
  }
})

/**
 * 在 SPA 应用中可用于在 pinia 实例被激活前使用 store
 * 在 SSR 应用中可用于在 setup 外使用 store
 */
export function useUserStoreHook() {
  return useUserStore(pinia)
}
